package handler

import (
	"crypto/md5"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"strings"
	"time"
	"yim_server/common/response"
	"yim_server/utils"
	"yim_server/yim_file/file_api/internal/logic"
	"yim_server/yim_file/file_api/internal/svc"
	"yim_server/yim_file/file_api/internal/types"
	"yim_server/yim_file/file_rpc/types/file_rpc"

	"github.com/zeromicro/go-zero/rest/httpx"
)

func imageUploadHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var req types.ImageRequest
		if err := httpx.Parse(r, &req); err != nil {
			response.Response(r, w, nil, err)
			return
		}

		file, fileHeader, err := r.FormFile("image")
		if err != nil {
			response.Response(r, w, nil, err)
			return
		}
		// 文件限制大小 换算 字节
		if fileHeader.Size > svcCtx.Config.FileSize {
			mSize := float64(svcCtx.Config.FileSize) / float64(1024) / float64(1024)
			response.Response(r, w, nil, fmt.Errorf("图片大小超过限制，最大只能上传%.2fMB大小的图片", mSize))
			return
		}

		// 文件后缀白名单
		nameList := strings.Split(fileHeader.Filename, ".")
		if len(nameList) < 2 {
			response.Response(r, w, nil, errors.New("请上传含后缀的图片"))
			return
		}

		var suffix string
		suffix = nameList[len(nameList)-1]
		if !utils.IsList(svcCtx.Config.WhiteList, suffix) {
			response.Response(r, w, nil, errors.New("图片非法"))
			return
		}
		// 图片上传
		imageType := r.FormValue("imageType")
		if imageType == "" {
			response.Response(r, w, nil, errors.New("图片类型不能为空"))
			return
		}

		switch imageType {
		case "avatar", "group_avatar", "chat":
		default:
			response.Response(r, w, nil, errors.New("图片类型非法"))
			return
		}

		// 保存文件
		byteData, err := io.ReadAll(file)
		if err != nil {
			response.Response(r, w, nil, err)
			return
		}

		// 计算 MD5 哈希值
		harsher := md5.New()
		_, _ = harsher.Write(byteData) // 忽略错误，或者处理错误
		hashBytes := harsher.Sum(nil)
		md5Hash := hex.EncodeToString(hashBytes)

		// 查看相同的md5是否存在
		fileExist, err := svcCtx.FileRpc.FileIsExist(r.Context(), &file_rpc.FileIsExistRequest{Hash: md5Hash, UserId: uint32(req.UserID)})
		if err != nil {
			response.Response(r, w, nil, err)
			return
		}
		// 不存在，则上传
		if !fileExist.IsExist {
			// 获取当前日期
			today := time.Now().Format("20060102")

			// 创建文件夹
			dirPath := path.Join("uploads", imageType, today)
			// 判断文件夹是否存在
			if _, err := os.Stat(dirPath); os.IsNotExist(err) {
				// 创建文件夹
				if err := os.MkdirAll(dirPath, 0755); err != nil {
					response.Response(r, w, nil, err)
					return
				}
			}

			// 生成唯一文件名
			timestamp := time.Now().UnixNano()
			fileName := fmt.Sprintf("%s%d.%s", today, timestamp, suffix)

			// 完整文件路径
			filePath := path.Join(dirPath, fileName)

			if err := os.WriteFile(filePath, byteData, 0666); err != nil {
				response.Response(r, w, nil, err)
				return
			}

			l := logic.NewImageUploadLogic(r.Context(), svcCtx)
			fileData := logic.FileData{
				FileName:      fileName,
				FileType:      imageType,
				FileUrl:       filePath,
				FileHash:      md5Hash,
				FileSize:      fileHeader.Size,
				FileExtension: suffix,
			}
			resp, err := l.ImageUpload(&req, &fileData)
			resp.Url = "/" + filePath
			response.Response(r, w, resp, err)
		} else {
			response.Response(r, w, map[string]string{"url": "/" + fileExist.Url}, err)
		}
	}
}
